﻿#include <stdio.h>
int main()
{
	char c = 1;
	printf("%u\n", sizeof(c));//1
	printf("%u\n", sizeof(+c));//4,发生了整型提升
	printf("%u\n", sizeof(-c));//4,发生了整型提升
	return 0;
}
//c只要参与运算，就会发生整型提升，虽然sizeof（）中的表达式不会“进行”运算。

//#include <stdio.h>
//int main()
//{
//	int x = 0x11223344;
//	char* p = &x;
//	*p = 0;
//	return 0;
//}
//观察到内存中44 33 22 11，被改成00 33 22 11，
//因为char*的指针解引用只有一个字节的访问权限


//指针-指针（求字符串长度）
//#include <stdio.h>
//int my_strlen(char* s)
//{
//	char* p = s;
//	while (*p != '\0')
//	{
//		p++;
//	}
//	return p - s;/*指针-指针得到的是两指针间的元素个数*/
//}
//int main()
//{
//	printf("%d\n", my_strlen("abcd"));
//	return 0;
//}


//#define _CRT_SECURE_NO_WARNINGS
//#include <stdio.h>
//int main()
//{
//    int arr[5] = { 0 };
////    指针关系运算
//    for (int* p = &arr[5]; p > &arr[0];)
//    {
//        *--p = 1;
//    }
//    return 0;
//}


//#define _CRT_SECURE_NO_WARNINGS
//#include <stdio.h>
//int main()
//{
//    int a = 0;
//    int* p = &a;
//    int** pp = &p; 
//    return 0;
//}


//#define _CRT_SECURE_NO_WARNINGS
//#include <stdio.h>
//int main()
//{
//    int* p = NULL;
//    int* l = 0;
//    int arr[2] = { 1,2 };
//    //arr = &arr[1];
//    p = &arr[1];
//    printf("%d\n", sizeof(p));
//    printf("%d\n", *p);
//    return 0;
//}


//判断当前机器的字节序
//#define _CRT_SECURE_NO_WARNINGS
//#include <stdio.h>
//int check_sys()
//{
//	int a = 1;
//	char* p = (char*)&a;
//	return *p;
//}
//int main()
//{
//	if (check_sys() == 1)
//		printf("小端\n");
//	else
//		printf("大端\n");
//	return 0;
//}


//int main()
//{
//	char a = -1;
//	signed char b = -1;
//	unsigned char c = -1;
//	//发生整型提升
//	printf("%d %d %d", a, b, c);//-1,-1,255
//	return 0;
//}


//int main()
//{
//	char a = -128;
//	char b = 128;
//	printf("%u\n", a);//4294967168(无符号整型原反补相同)
//	printf("%d\n", a);//-128
//	printf("%u\n", b);//4294967168
//	return 0;
//}


//#include <string.h>
//int main()
//{
//	char a[1000];
//	int i = 0;
//	for (i = 0; i < 1000; i++)
//	{
//		a[i] = -1 - i;
//	}
//	//-1 -2 -3 ...... -127 -128 127 126 ....  3 2 1 0 -1 -2
//	printf("%d\n", strlen(a));//找\0-->0 128+127=225
//	return 0;
//}

//int main()
//{
//	int n = 9;
//	float a = 5.5;
//	return 0;
//}

//int main()
//{
//	int n = 9;
//	float* pFloat = (float*)&n;
//	printf("n的值为：%d\n", n);
//	printf("*pFloat的值为：%f\n", *pFloat);
//	*pFloat = 9.0;
//	printf("num的值为：%d\n", n);
//	printf("*pFloat的值为：%f\n", *pFloat);
//	return 0;
//}

//结果说明整型和浮点型在内存中的存储方式是不同的


//int main()
//{
//	double a = 5.5;
//	return 0;
//}



//int main()
//{
//	int i = 0;
//	int arr[10] = { 0 };
//	for (i = 0; i <= 12; i++)
//	{
//		arr[i] = 0;
//		printf("hehe\n");
//	}
//	return 0;
//}
//结果死循环，因为这样定义的情况下，i的地址和arr[12]的地址是一样的
//i和数组是局部变量(i先创建的），局部变量是定义在栈区的，栈区内存的使用习惯是先使用高地址，再使用低地址
//，而数组元素的地址随着下标的增加而增加，所以数组元素在向后越界访问的时候，就有可能访问到i，
//一旦访问到i并将i置成0，就会发生死循环

//my_strcpy的实现（版本1）模拟实现库函数strcpy
//void my_strcpy(char* dest, char* sou)
//{
//	while (*sou != '\0')
//	{
//		*dest = *sou;
//		dest++;
//		sou++;
//	}
//	*dest = *sou;
//}

//版本2(优化)
//void my_strcpy(char* dest, char* sou)
//{
//	while (*sou)
//	{
//		*dest++ = *sou++;
//	}
//	*dest = *sou;
//}


//版本3(再优化)
//#include <assert.h>
//void my_strcpy(char* dest, char* sou)
//{
//	while (*dest++ = *sou++);//既拷贝了\0,又终止了循环
//
//}


//版本4(再优化)
//#include <assert.h>
//void my_strcpy(char* dest, char* sou)
//{
//	assert(sou != NULL);//断言,包含在头文件<assert.h>中
//	assert(dest != NULL);
//	while (*dest++ = *sou++);//既拷贝了\0,又终止了循环
//
//}

//版本5(库函数strcpy的实现方式)
//#include <assert.h>
//char* my_strcpy(char* dest, const char* sou)
//{
//	assert(sou != NULL);//断言,包含在头文件<assert.h>中
//	assert(dest != NULL);
//	char* ret = dest;
//	while (*dest++ = *sou++);//既拷贝了\0,又终止了循环
//	return ret;
//}
//
//
//int main()
//{
//	char arr1[15] = "xxxxxxxxx";
//	char arr2[] = "hello";
//	printf("%s\n", arr1);
//	//自己定义一个函数模拟实现字符串拷贝函数
//	//my_strcpy(arr1, arr2);
//	//strcpy(arr1, arr2);//字符串拷贝函数，\0也会拷过去
//	printf("%s\n", my_strcpy(arr1, arr2));
//	return 0;
//}



//模拟实现库函数strlen
//#include <assert.h>
//int my_strlen(const char *p)
//{
//	//assert(p != NULL);或
//	assert(p);
//	int i = 0;
//	while (*p++)
//		i++;
//	return i;
//}
//
//int main()
//{
//	char arr[] = "abcdef";
//	printf("%d\n", my_strlen(arr));
//	return 0;
//}


//int main()
//{
//	//const修饰一个变量，这个变量被称为常变量，具有常属性，不能被修改，但本质上还是变量
//	const int num = 10;
//	//但此时通过指针的方法还是可以间接num修改的值，要想通过指针也不能修改，在*左边加const,修饰*p
//	//*p不能被改变，但是p还是可以被改变;若放在*右边，则p不能被改变
//	int const* p = &num;
//	//*p = 20;
//	//若放在*右边，则p不能被改变,*p可以
//	int* const p = &num;
//	printf("%d\n", num);
//	return 0;
//}


//#include <stdio.h>
//int main()
//{
//	char* p = "hello bit";
//	//本质上是把"hello bit"这个字符串的首元素地址存在了p中
//	char arr[] = "hello bit";
//	printf("%s\n", p);
//	printf("%s\n", arr);
//	return 0;
//}



//int main()
//{
//	char str1[] = "hello bit.";
//	char str2[] = "hello bit.";
//	const char* str3 = "hello bit.";//常量字符串，不能被改变，而且多个相同的常量字符串在内存中只有一份留存
//	const char* str4 = "hello bit.";
//	printf("%p\n", str3);
//	printf("%p\n", str4);
//	if (str1 == str2)//not same
//		printf("str1 and str2 are same\n");
//	else
//		printf("str1 and str2 are not same\n");
//
//	if (str3 == str4)//same
//		printf("str3 and str4 are same\n");
//	else
//		printf("str3 and str4 are not same\n");
//
//	return 0;
//}


//int main()
//{
//	int a[5] = { 1,2,3,4,5 };
//	int b[5] = { 3,4,5,7,8 };
//	int c[5] = { 6,7,8,9,5 };
//	int* arr[3] = { a,b,c };//整型指针数组
//	int i = 0;
//	for (i = 0; i < 3; i++)
//	{
//		int j = 0;
//		for (j = 0; j < 5; j++)
//		{
//			//printf("%d ", *(arr[i] + j));
//			printf("%d ", arr[i][j]);
//		}
//		printf("\n");
//	}
//	return 0;
//}


//int main()
//{
//	int arr[10] = { 0 };
//	//两个printf打印出来的结果一样，但意义不一样
//	//printf("%p\n", arr);//arr是数组名，表示首元素的地址
//	//printf("%p\n", &arr);//&arr是取出了数组的地址，表示的是这个数组的地址
//	
//	int* p1 = arr;
//	int(*p2)[10] = &arr;
//	//p1,p2打印出来的结果一样,但p1+1,p2+1不一样
//	printf("%p\n", p1);
//	printf("%p\n", p1+1);
//	//p1是一个整形指针，+1跳过4个字节
//	printf("%p\n", p2);
//	printf("%p\n", p2+1);
//	//p2是一个整型数组指针，大小为40字节，所以+1跳过40个字节
//	return 0;
//}



//#include <stdio.h>
//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
//	int(*p)[10] = &arr;//把数组arr的地址赋值给数组指针变量p
//	//但是我们一般很少这样写代码
//	return 0;
//}


//#include <stdio.h>
////常规写法
//void print_arr1(int arr[3][5], int row, int col) {
//	int i = 0;
//	for (i = 0; i < row; i++)
//	{
//		int j = 0;
//		for (j = 0; j < col; j++)
//		{
//			printf("%d ", arr[i][j]);
//		}
//		printf("\n");
//	}
//}
////运用数组指针
//void print_arr2(int(*arr)[5], int row, int col) {
//	int i = 0;
//	for (i = 0; i < row; i++)
//	{
//		int j = 0;
//		for (j = 0; j < col; j++)
//		{
//			printf("%d ", arr[i][j]);
//		}
//		printf("\n");
//	}
//}
//int main()
//{
//	int arr[3][5] = { 1,2,3,4,5,6,7,8,9,10 };
//	print_arr1(arr, 3, 5);
//	//数组名arr，表示首元素的地址
//	//但是二维数组的首元素是二维数组的第一行
//	//所以这里传递的arr，其实相当于第一行的地址，是一维数组的地址
//	//可以数组指针来接收
//	print_arr2(arr, 3, 5);
//	return 0;
//}